{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "## 张量的定义"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "---"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "source": [
    "import os\r\n",
    "from pathlib import Path\r\n",
    "\r\n",
    "print('WD:',os.getcwd())\r\n",
    "# os.chdir()\r\n",
    "PATH = Path().cwd()\r\n",
    "print('PATH:',PATH)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "WD: c:\\files\\git_repository\\pytorch-learning\\pytorch基础入门实战\\0张量的定义\n",
      "PATH: c:\\files\\git_repository\\pytorch-learning\\pytorch基础入门实战\\0张量的定义\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 介绍"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "PyTorch 中的所有操作都是在张量的基础上进行的，本实验主要讲解了张量定义和相关张量操作以及 GPU 和张量之间的关系，为以后使用 PyTorch 进行深度学习打下坚实的基础。"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 知识点"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "- 张量的定义\n",
    "- 张量的运算\n",
    "- 张量的切片\n"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "---"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 张量"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 张量的定义"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "PyTorch 中的所有内容都基于 Tensor(张量) 操作的。张量可以具有不同的尺寸，它可以是 1 维（标量），2 维（矢量），甚至 3 维（矩阵）或更高。让我们看一下如何在 PyTorch 中创建张量。\n"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "source": [
    "import torch\r\n",
    "\r\n",
    "# 利用 torch.empty() 初始化指定大小的张量，如果不指定值的话，内容为随机值\r\n",
    "# 传入的参数为想创建的张量大小\r\n",
    "x = torch.empty(1)  # scalar，大小为 1*1 的张量\r\n",
    "print(x.size())\r\n",
    "x = torch.empty(3)  # vector, 1D，大小为 1*3 的张量\r\n",
    "print(x.size())\r\n",
    "x = torch.empty(2, 3)  # matrix, 2D，大小为 2*3 的张量\r\n",
    "print(x.size())\r\n",
    "x = torch.empty(2, 2, 3)  # tensor, 3D，大小为 2*2*3 的张量\r\n",
    "print(x.size())"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "torch.Size([1])\n",
      "torch.Size([3])\n",
      "torch.Size([2, 3])\n",
      "torch.Size([2, 2, 3])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "<i class=\"fa fa-arrow-circle-down\" aria-hidden=\"true\"> 动手练习</i>｜如果你对课程所使用的蓝桥云课 Notebook 在线环境并不熟悉，可以先学习 [<i class=\"fa fa-external-link-square\" aria-hidden=\"true\"> 使用指南课程</i>](https://www.lanqiao.cn/courses/1322)。"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "source": [
    "import torch\r\n",
    "x = torch.empty(1)\r\n",
    "print(x.size())\r\n",
    "x = torch.empty(2,3)\r\n",
    "print(x.size())\r\n",
    "x = torch.empty(4,5,6)\r\n",
    "print(x.size())"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "torch.Size([1])\n",
      "torch.Size([2, 3])\n",
      "torch.Size([4, 5, 6])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "如果我们需要随机初始化值在 0-1 之间的张量（服从均匀分布），可以使用 `torch.rand(size)`："
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "source": [
    "# torch.rand(size)\r\n",
    "torch.rand(5, 3)  # 初始化 5*3 大小的 0-1 之间的张量"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "tensor([[0.4146, 0.8149, 0.6460],\n",
       "        [0.6931, 0.5550, 0.0953],\n",
       "        [0.5850, 0.1969, 0.7599],\n",
       "        [0.2702, 0.7117, 0.4180],\n",
       "        [0.4832, 0.1545, 0.9141]])"
      ]
     },
     "metadata": {},
     "execution_count": 5
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "source": [
    "print(torch.randn(1,2))"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "tensor([[1.4854, 1.2710]])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "如果我们想初始化全为 1 或者全为 0 的张量，可以使用 `torch.zeros(size)` 和 `torch.ones(size)`："
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "source": [
    "x = torch.zeros(5, 3)\r\n",
    "y = torch.ones(5, 3)\r\n",
    "print(x)\r\n",
    "print(y)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "tensor([[0., 0., 0.],\n",
      "        [0., 0., 0.],\n",
      "        [0., 0., 0.],\n",
      "        [0., 0., 0.],\n",
      "        [0., 0., 0.]])\n",
      "tensor([[1., 1., 1.],\n",
      "        [1., 1., 1.],\n",
      "        [1., 1., 1.],\n",
      "        [1., 1., 1.],\n",
      "        [1., 1., 1.]])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "source": [
    "print(torch.ones(1,2))\r\n",
    "print(torch.zeros(1,2))"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "tensor([[1., 1.]])\n",
      "tensor([[0., 0.]])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "可以通过 `x.size()` 得到某个张量的大小："
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "source": [
    "x.size()"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "torch.Size([5, 3])"
      ]
     },
     "metadata": {},
     "execution_count": 9
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "source": [
    "print(x.size())\r\n",
    "print(x.shape)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "torch.Size([5, 3])\n",
      "torch.Size([5, 3])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "可以通过 `x.dtype` 查看 x 中值的具体类型："
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "source": [
    "x.dtype"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "torch.float32"
      ]
     },
     "metadata": {},
     "execution_count": 11
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "source": [
    "print(x.dtype)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "torch.float32\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "当然，也可以在初始化时传入  `dtype` 参数，指定数组值的类型："
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "source": [
    "x = torch.zeros(5, 3, dtype=torch.float16)\r\n",
    "print(x)\r\n",
    "\r\n",
    "# check type\r\n",
    "print(x.dtype)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "tensor([[0., 0., 0.],\n",
      "        [0., 0., 0.],\n",
      "        [0., 0., 0.],\n",
      "        [0., 0., 0.],\n",
      "        [0., 0., 0.]], dtype=torch.float16)\n",
      "torch.float16\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "source": [
    "x = torch.empty(2,3,dtype=torch.int64)\r\n",
    "print(x)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "tensor([[0, 0, 0],\n",
      "        [0, 0, 0]])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "如果我们需要创建指定值的张量，我们可以使用 ` torch.tensor(list)`，list 可以为 NumPy 中的一个列表。"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "source": [
    "#创建的张量中的值为 [5.5,3]\r\n",
    "x = torch.tensor([5.5, 3])\r\n",
    "print(x)\r\n",
    "print(x.size())"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "tensor([5.5000, 3.0000])\n",
      "torch.Size([2])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "source": [
    "x = torch.tensor([5.1,2])\r\n",
    "print(x)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "tensor([5.1000, 2.0000])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "如果想要定义的张量能够自动计算梯度（后面会说明用处），那么我们就需要将参数 `requires_grad` 置为 `True`。"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "source": [
    "torch.tensor([5.5, 3], requires_grad=True)"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "tensor([5.5000, 3.0000], requires_grad=True)"
      ]
     },
     "metadata": {},
     "execution_count": 17
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "source": [
    "torch.tensor([1.0,2,3],requires_grad=True)\r\n",
    "# Only Tensors of   floating point and complex dtype can require gradients"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "tensor([1., 2., 3.], requires_grad=True)"
      ]
     },
     "metadata": {},
     "execution_count": 18
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 张量的运算"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "张量的加法："
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "source": [
    "y = torch.rand(2, 2)\r\n",
    "x = torch.rand(2, 2)\r\n",
    "z = x + y\r\n",
    "z"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "tensor([[0.4700, 1.6503],\n",
       "        [0.2551, 0.5692]])"
      ]
     },
     "metadata": {},
     "execution_count": 19
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "source": [
    "x = torch.tensor([1,2])\r\n",
    "y = torch.tensor([1,2])\r\n",
    "print(x+y)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "tensor([2, 4])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "张量的减法："
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "source": [
    "# 使用 - 或者 .sub 都可以表示张量减法\r\n",
    "z = x - y\r\n",
    "print(z)\r\n",
    "z = torch.sub(x, y)\r\n",
    "print(z)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "tensor([0, 0])\n",
      "tensor([0, 0])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "source": [
    "print(x-y)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "tensor([0, 0])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "张量乘法（利用 `*` 或者 `torch.mul`表示）："
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "source": [
    "# 张量乘法\r\n",
    "z = x * y\r\n",
    "print(z)\r\n",
    "z = torch.mul(x, y)\r\n",
    "print(z)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "tensor([1, 4])\n",
      "tensor([1, 4])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "source": [
    "# 逐个元素，对应相乘\r\n",
    "print(x*y)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "tensor([1, 4])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "张量除法(使用 `/` 或者 `torch.div` 表示)："
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "source": [
    "# 张量除法\r\n",
    "z = x / y\r\n",
    "print(z)\r\n"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "tensor([1., 1.])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "source": [
    "z = torch.div(x, y)\r\n",
    "print(z)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "tensor([1., 1.])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "source": [
    "# 对应相除\r\n",
    "print(x/y)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "tensor([1., 1.])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 张量的切片"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "和 NumPy 的切片类似，如下："
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "source": [
    "x = torch.rand(5, 3)\r\n",
    "print(x)\r\n",
    "print(x[1, 1])  # 第一个值表示第一维（即行号），第二个值表示第二维（即列号）\r\n",
    "print(x[:, 0])  # 所有的行中的第 1 列\r\n",
    "print(x[1, :])  # 第 2 行中所有的列"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "tensor([[0.3173, 0.0360, 0.4783],\n",
      "        [0.5517, 0.0321, 0.4257],\n",
      "        [0.6707, 0.1490, 0.8146],\n",
      "        [0.2362, 0.1982, 0.8083],\n",
      "        [0.7112, 0.9616, 0.0227]])\n",
      "tensor(0.0321)\n",
      "tensor([0.3173, 0.5517, 0.6707, 0.2362, 0.7112])\n",
      "tensor([0.5517, 0.0321, 0.4257])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "source": [
    "# 对于区间，一般来说都是左闭右开\r\n",
    "x = torch.arange(1,13).reshape((3,4))\r\n",
    "print(x)\r\n",
    "print(x[1][1])\r\n",
    "print(x[:][0])"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "tensor([[ 1,  2,  3,  4],\n",
      "        [ 5,  6,  7,  8],\n",
      "        [ 9, 10, 11, 12]])\n",
      "tensor(6)\n",
      "tensor([1, 2, 3, 4])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 张量的重塑"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "重塑的意思就是将原张量的形状进行变换，即元素总个数不变的情况下改变行数和列数，使用 `torch.view(size)` 类似于 `numpy.reshape`。"
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "source": [
    "x = torch.randn(4, 4)\r\n",
    "y = x.view(16)  # 指定改变后的大小\r\n",
    "z = x.view(2, 8)\r\n",
    "print(x.size(), y.size(), z.size())"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "source": [
    "x = torch.randn(4,4)\r\n",
    "y = x.view(16)\r\n",
    "z = x.view(2,8)\r\n",
    "print(x.size(), y.size(), z.size())"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "当 x 的大小为 $12\\times23\\times32$ ，而我们想把 x 转为 $2\\times m$ 的大小时，我们就必须手动算出 $12\\times23\\times32$ 的值，然后除以 2，进而得到 m 的值。"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "为了避免这种情况，我们可以将 m 所在位置赋为 -1。计算机看到 -1 时，会自动使用  $12\\times23\\times32 ÷ 2$ 的值来替换 -1："
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "source": [
    "x = torch.randn(12, 23, 32)\r\n",
    "y = x.view(2, -1)  # 将需要计算的那个维度直接用 -1 表示 12*23*32/2 的值\r\n",
    "x.size(), y.size()"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "(torch.Size([12, 23, 32]), torch.Size([2, 4416]))"
      ]
     },
     "metadata": {},
     "execution_count": 32
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "source": [
    "x = torch.randn(10,10)\r\n",
    "print(x.view(2,-1).size())"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "torch.Size([2, 50])\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "注意：一次切片中只能有一个位置值 -1 。"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### NumPy 与 Tensor"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "可以使用 `tensor.numpy()` 将 Tensor 类型的变量转为 NumPy 类型："
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "source": [
    "a = torch.ones(5)\r\n",
    "print(a)\r\n",
    "\r\n",
    "b = a.numpy()\r\n",
    "print(b)\r\n",
    "print(type(b))"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "tensor([1., 1., 1., 1., 1.])\n",
      "[1. 1. 1. 1. 1.]\n",
      "<class 'numpy.ndarray'>\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "source": [
    "a = torch.zeros(1,2,3)\r\n",
    "na = a.numpy()\r\n",
    "print(type(a))\r\n",
    "print(type(na))"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "<class 'torch.Tensor'>\n",
      "<class 'numpy.ndarray'>\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    " 可以使用 `torch.from_numpy()` 将 NumPy 类型的变量转为 Tensor："
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "source": [
    "import numpy as np\r\n",
    "a = np.ones(5)\r\n",
    "b = torch.from_numpy(a)\r\n",
    "print(a)\r\n",
    "print(b)"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "[1. 1. 1. 1. 1.]\n",
      "tensor([1., 1., 1., 1., 1.], dtype=torch.float64)\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "source": [
    "import numpy as np\r\n",
    "a = np.array([1, 2, 3])\r\n",
    "ta = torch.from_numpy(a)\r\n",
    "print(type(a))\r\n",
    "print(type(ta))"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "<class 'numpy.ndarray'>\n",
      "<class 'torch.Tensor'>\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### GPU 上创建张量"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "默认情况下，所有的张量都是在 CPU 上创建的，但是你也可以使用 GPU 创建它，或者将 CPU 创建的向量移动到 GPU 中。"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "当然，下面代码只有在你的电脑支持 GPU 的情况下才能运行。"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "我们可以通过 ` torch.cuda.is_available()` 命令，查看本地环境时候支持 GPU ："
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "source": [
    "torch.cuda.is_available()"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "metadata": {},
     "execution_count": 40
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "source": [
    "torch.cuda.is_available()"
   ],
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "metadata": {},
     "execution_count": 41
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "- True 表示支持\n",
    "- False 表示不支持"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "由于 GPU 成本过高，本实验我们暂且不使用（将其用在刀刃上），所以线上环境会返回 False。"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "由于本章节没有配置 GPU ，因此下面两段代码只能阐述一下了。"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "将变量放到 GPU 中运行的方式有两种，如下："
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "- 在定义时就指定参数 `device`\n",
    "        # 如果支持 GPU 则传入字符串 cuda，否则传入 cpu\n",
    "        device = torch.device(\"cuda\")         \n",
    "        y = torch.ones_like(x, device=device)  # 在 GPU 上直接创建张量\n",
    "- 创建张量后，将变量移动到 GPU 中\n",
    "\n",
    "        x = torch.randn(4, 4)\n",
    "        device = torch.device(\"cuda\")           \n",
    "        x = x.to(device)                       # 将张量移动到 GPU\n"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 实验总结"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "本实验主要讲解了张量的定义，以及如何使用 PyTorch 完成张量的加、减、乘、除、切片和重塑等操作。在实验的最后，我们对张量进行了扩展，阐述了如何查看本地环境是否支持 GPU ，以及如何将变量定义到 GPU 之中。"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "<hr><div style=\"color: #999; font-size: 12px;\"><i class=\"fa fa-copyright\" aria-hidden=\"true\"> 本课程内容版权归蓝桥云课所有，禁止转载、下载及非法传播。</i></div>"
   ],
   "metadata": {}
  }
 ],
 "metadata": {
  "kernelspec": {
   "name": "python3",
   "display_name": "Python 3.8.0 64-bit ('pytorch': conda)"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.0"
  },
  "interpreter": {
   "hash": "95edf26445b41d81dc60008cc593bb3c243ca80a3a822915e2b6f7013280bc10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}